import _ from 'lodash'
import { existsSync, mkdirSync, appendFileSync } from 'fs'
import { join } from 'path'

class Logger {
  constructor(config = {}) {
    this.config = _.defaults(config, {
      type: 'File',
      options: {
        level: 'info',
        colors: true,
        moduleColors: false,
        filename: 'zitmapx-{date}.log'
      }
    })
    
    this.levels = {
      error: 0,
      warn: 1,
      info: 2,
      debug: 3
    }
    
    this.colors = {
      error: '\x1b[31m',
      warn: '\x1b[33m',
      info: '\x1b[36m',
      debug: '\x1b[90m',
      reset: '\x1b[0m'
    }
    
    this.currentLevel = this.levels[this.config.options.level] || this.levels.info
    this.logFile = null
    this.logStream = null
    
    if (this.config.type === 'File') {
      this.initFileLogging()
    }
  }
  
  initFileLogging() {
    const filename = this.config.options.filename
      .replace('{date}', new Date().toISOString().split('T')[0])
    
    const logDir = join(process.cwd(), 'logs')
    if (!existsSync(logDir)) {
      mkdirSync(logDir, { recursive: true })
    }
    
    this.logFile = join(logDir, filename)
  }
  
  format(level, module, message, meta = {}) {
    const timestamp = new Date().toISOString()
    const moduleStr = module ? `[${module}]` : ''
    const metaStr = _.isEmpty(meta) ? '' : ' ' + JSON.stringify(meta)
    
    return {
      console: this.formatConsole(level, timestamp, moduleStr, message, metaStr),
      file: this.formatFile(timestamp, level.toUpperCase(), moduleStr, message, metaStr)
    }
  }
  
  formatConsole(level, timestamp, moduleStr, message, metaStr) {
    if (!this.config.options.colors) {
      return `${timestamp} ${level.toUpperCase()} ${moduleStr} ${message}${metaStr}`
    }
    
    const color = this.colors[level] || this.colors.reset
    const moduleColor = this.config.options.moduleColors ? '\x1b[35m' : ''
    
    return `${this.colors.reset}${timestamp} ${color}${level.toUpperCase()}${this.colors.reset} ${moduleColor}${moduleStr}${this.colors.reset} ${message}${metaStr}`
  }
  
  formatFile(timestamp, level, moduleStr, message, metaStr) {
    return `${timestamp} ${level} ${moduleStr} ${message}${metaStr}\n`
  }
  
  writeToFile(content) {
    if (!this.logFile) return
    
    try {
      // 使用 fs.appendFileSync 实现追加写入
      appendFileSync(this.logFile, content, 'utf8')
    } catch (error) {
      console.error('Failed to write log file:', error)
    }
  }
  
  log(level, module, message, meta) {
    if (this.levels[level] === undefined) return
    if (this.levels[level] > this.currentLevel) return
    
    const formatted = this.format(level, module, message, meta)
    
    // 输出到控制台
    console.log(formatted.console)
    
    // 写入文件
    if (this.config.type === 'File') {
      this.writeToFile(formatted.file)
    }
  }
  
  // 便捷方法
  error(module, message, meta) {
    this.log('error', module, message, meta)
  }
  
  warn(module, message, meta) {
    this.log('warn', module, message, meta)
  }
  
  info(module, message, meta) {
    this.log('info', module, message, meta)
  }
  
  debug(module, message, meta) {
    this.log('debug', module, message, meta)
  }
  
  // 创建子logger
  child(module) {
    const self = this
    return {
      error: (message, meta) => self.error(module, message, meta),
      warn: (message, meta) => self.warn(module, message, meta),
      info: (message, meta) => self.info(module, message, meta),
      debug: (message, meta) => self.debug(module, message, meta)
    }
  }
  
  // 设置日志级别
  setLevel(level) {
    if (this.levels[level] !== undefined) {
      this.currentLevel = this.levels[level]
      this.config.options.level = level
    }
  }
  
  // 获取当前日志级别
  getLevel() {
    return this.config.options.level
  }
}

// 创建单例
let instance = null

export const createLogger = (config) => {
  if (!instance) {
    instance = new Logger(config)
  }
  return instance
}

export const getLogger = () => {
  if (!instance) {
    instance = new Logger()
  }
  return instance
}

export default { createLogger, getLogger }